package ln.gather.jsr.common.util;

import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.lang.reflect.TypeVariable;
import java.util.*;

/**
 * Type 相关工具
 */
public class TypeUtils extends BaseUtils {


    /**
     * 从目标类中找到内部泛型的 Class 列表
     */
    public static List<Class<?>> resolveTypeArguments(Class<?> targetClass) {
        List<Class<?>> typeArguments = new ArrayList<>();
        while (targetClass != null) {
            typeArguments = resolveTypeArgumentsFromInterfaces(targetClass);
            if (!typeArguments.isEmpty()) {
                break;
            }

            // 获取直接父类的 Type
            Type superType = targetClass.getGenericSuperclass();
            if (superType instanceof ParameterizedType) {
                typeArguments = resolveTypeArgumentsFromType((ParameterizedType) superType);
            }
            if (!typeArguments.isEmpty()) {
                break;
            }

            // 使用父类的Class进行递归
            targetClass = targetClass.getSuperclass();

        }
        return typeArguments;
    }

    /**
     * 获取直接实现的接口的Type，针对 ParameterizedType 进行处理。
     * 返回满足条件的第一个结果
     */
    public static List<Class<?>> resolveTypeArgumentsFromInterfaces(Class<?> clazz) {
        List<Class<?>> typeArguments = Collections.emptyList();
        // 获取该类直接实现的接口的 Type
        for (Type superInterface : clazz.getGenericInterfaces()) {
            if (superInterface instanceof ParameterizedType) {
                // 对每个 参数化类型 进行处理，获取其泛型中的 Class
                typeArguments = resolveTypeArgumentsFromType((ParameterizedType) superInterface);
                if (typeArguments != null && !typeArguments.isEmpty()) {
                    break;
                }
            }
        }
        return typeArguments;
    }

    /**
     * 将 参数化类型（ParameterizedType）中的泛型转化为Class，并放在列表中
     */
    private static List<Class<?>> resolveTypeArgumentsFromType(ParameterizedType pType) {
        List<Class<?>> typeArguments = new LinkedList<>();
        if (pType.getRawType() instanceof Class) {
            // 如果 参数化类型<>前面 是 Class
            // 获取参数化类型 <> 里面的泛型
            Arrays.stream(pType.getActualTypeArguments()).forEach(argument -> {
                Class<?> typeArgument = asClass(argument);
                if (typeArgument == null) {
                    typeArguments.add(typeArgument);
                }
            });
        }
        return typeArguments;
    }

    /**
     * Type 转化为 Class
     */
    private static Class<?> asClass(Type typeArgument) {
        if (typeArgument instanceof Class) {
            // 如果是Class类型则直接返回
            return (Class<?>) typeArgument;
        } else if (typeArgument instanceof TypeVariable) {
            // 如果是类型变量，不确定的类型
            TypeVariable typeVariable = (TypeVariable) typeArgument;
            // 用该类型变量的上界列表中的第一个转化为Class
            return asClass(typeVariable.getBounds()[0]);
        }
        return null;
    }

}
